package com.baseframe.tool.utils.data;

import lombok.SneakyThrows;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class WrapperHandler implements Wrapper {

    @Override
    public <S, T> T wrap(S source, T target, String... attributes) {

        List<String> attributeList = Arrays.asList(attributes);
        Class<?> sourceClazz = source.getClass();
        Class<?> targetClazz = target.getClass();

        Field[] sourceFields = getAllFields(sourceClazz);
        Field[] targetFields = getAllFields(targetClazz);

        for (Field sourceField : sourceFields) {
            //排除排除掉的字段
            if (attributeList.contains(sourceField.getName())) {
                continue;
            }
            for (Field targetField : targetFields) {


                if (sourceField.getName().equals(targetField.getName()) && sourceField.getType().equals(targetField.getType())) {


                    try {
                        //调用 source get方法 调用target的set方法
                        PropertyDescriptor sourceDescriptor = new PropertyDescriptor(sourceField.getName(), sourceClazz);

                        Object value = sourceDescriptor.getReadMethod().invoke(source);
                        if (value==null){
                            continue;
                        }
                        //执行target的set方法
                        PropertyDescriptor targetDescriptor = new PropertyDescriptor(targetField.getName(), targetClazz);
                        targetDescriptor.getWriteMethod().invoke(target, value);

                    } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }


                }
            }
        }

        return target;
    }

    /**
     * 获取本类及其父类的字段属性
     * @param clazz 当前类对象
     * @return 字段数组
     */
    @Override
    public  Field[] getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        return fieldList.toArray(fields);
    }

}
